package com.xiaomaoguai.fcp.pre.kepler.router.async;

import com.xiaomaoguai.fcp.pre.kepler.router.lock.Spinlock;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.api.HandlerContext;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * RouterWorkPoolManager 线程池管理器 通过Spinlock保证增加删除串行操作 workPoolMap
 * 保存routerInfo的线程池名称和线程池的对应关系，获取线程池通过workPoolMap获取 countMap
 * 记录同名线程池创建次数，为0时需要workPoolMap.remove
 *
 * @author DH
 */
public class RouterWorkPoolManager {

	private static String DEFAULT_POOL_NAME = "defaultPool";

	private static Spinlock lock = new Spinlock();

	private static ConcurrentHashMap<String, WorkPool<HandlerContext<?>>> workPoolMap = new ConcurrentHashMap<String, WorkPool<HandlerContext<?>>>();

	private static HashMap<String, AtomicInteger> countMap = new HashMap<String, AtomicInteger>();

	static {
		WorkPool<HandlerContext<?>> workPool = new StandardWorkPool(20);
		workPool.start();
		workPoolMap.put(DEFAULT_POOL_NAME, workPool);
		countMap.put(DEFAULT_POOL_NAME, new AtomicInteger(1));
	}

	public static void addPool(AsyncInfo asyncInfo) {
		try {
			lock.lock();
			if (!workPoolMap.containsKey(asyncInfo.getAsyncWorkPool())) {
				WorkPool<HandlerContext<?>> routerWorkPool = new RouterWorkPool(asyncInfo.getAsyncWorkPool(), asyncInfo.getBufferSize(),
						asyncInfo.getWorkThreadNum());
				routerWorkPool.start();
				workPoolMap.put(asyncInfo.getAsyncWorkPool(), routerWorkPool);
			}
			AtomicInteger count = countMap.get(asyncInfo.getAsyncWorkPool());
			if (count == null) {
				countMap.put(asyncInfo.getAsyncWorkPool(), new AtomicInteger(1));
			} else {
				count.incrementAndGet();
			}
		} finally {
			lock.unlock();
		}
	}

	public static void removePool(String workPoolName) {
		try {
			lock.lock();
			WorkPool<HandlerContext<?>> workPool = workPoolMap.get(workPoolName);
			if (workPool != null && countMap.get(workPoolName).decrementAndGet() == 0) {
				workPoolMap.remove(workPoolName);
				workPool.shutdownGracefully();
			}
		} finally {
			lock.unlock();
		}
	}

	public static WorkPool<HandlerContext<?>> getPool(String workPoolName) {
		if (StringUtils.isBlank(workPoolName)) {
			workPoolName = DEFAULT_POOL_NAME;
		}
		WorkPool<HandlerContext<?>> workpool = workPoolMap.get(workPoolName);
		return workpool == null ? workPoolMap.get(DEFAULT_POOL_NAME) : workpool;
	}

	public static WorkPool<HandlerContext<?>> getDefaultPool() {
		return workPoolMap.get(DEFAULT_POOL_NAME);
	}

}
